import 'dart:async';
import 'dart:developer';
import 'dart:io';

import 'package:fep/bean/printer_device_info.dart';
import 'package:fep/bean/simple_account.dart';
import 'package:fep/utils/image_utils.dart';
import 'package:flutter_pos_printer_platform/esc_pos_utils_platform/esc_pos_utils_platform.dart';
import 'package:flutter_pos_printer_platform/flutter_pos_printer_platform.dart';


import 'package:flutter/services.dart';
import 'package:image/image.dart' as img;


import 'package:flutter_pos_printer_platform/esc_pos_utils_platform/src/capability_profile.dart';
import 'package:flutter_pos_printer_platform/esc_pos_utils_platform/src/enums.dart';
import 'package:flutter_pos_printer_platform/esc_pos_utils_platform/src/generator.dart';
import 'package:flutter_pos_printer_platform/esc_pos_utils_platform/src/pos_column.dart';


class PrintTools {

  var printerManager = PrinterManager.instance;

  // 挂起任务
  List<int>? pendingTask;

  var _reconnect = false;

  BTStatus _currentStatus = BTStatus.none;

  StreamSubscription<PrinterDevice>? _subscription;
  StreamSubscription<BTStatus>? _subscriptionBtStatus;
  StreamSubscription<USBStatus>? _subscriptionUsbStatus;
  StreamSubscription<TCPStatus>? _subscriptionTCPStatus;

  initPrint() {
    // subscription to listen change status of bluetooth connection
    _subscriptionBtStatus = PrinterManager.instance.stateBluetooth.listen((status) {
      log(' ----------------- status bt $status ------------------ ');
      _currentStatus = status;
      if (status == BTStatus.connected) {
        // setState(() {
        //   _isConnected = true;
        // });
      }
      if (status == BTStatus.none) {
        // setState(() {
        //   _isConnected = false;
        // });
      }
      if (status == BTStatus.connected && pendingTask != null) {
        if (Platform.isAndroid) {
          Future.delayed(const Duration(milliseconds: 1000), () {
            PrinterManager.instance.send(type: PrinterType.bluetooth, bytes: pendingTask!);
            pendingTask = null;
          });
        } else if (Platform.isIOS) {
          PrinterManager.instance.send(type: PrinterType.bluetooth, bytes: pendingTask!);
          pendingTask = null;
        }
      }
    });



    //  PrinterManager.instance.stateUSB is only supports on Android
    _subscriptionUsbStatus = PrinterManager.instance.stateUSB.listen((status) {
      log(' ----------------- status usb $status ------------------ ');
      // _currentUsbStatus = status;
      if (Platform.isAndroid) {
        if (status == USBStatus.connected && pendingTask != null) {
          Future.delayed(const Duration(milliseconds: 1000), () {
            PrinterManager.instance.send(type: PrinterType.usb, bytes: pendingTask!);
            pendingTask = null;
          });
        }
      }
    });



    //  PrinterManager.instance.stateUSB is only supports on Android
    _subscriptionTCPStatus = PrinterManager.instance.stateTCP.listen((status) {
      log(' ----------------- status tcp $status ------------------ ');
      // _currentTCPStatus = status;
    });

  }

  disposePrint() {
    _subscription?.cancel();
    _subscriptionBtStatus?.cancel();
    _subscriptionUsbStatus?.cancel();
    _subscriptionTCPStatus?.cancel();
  }

  void scanPrint(PrinterType printType, bool isBle, List<PrinterDeviceInfo> devices) {
    List<PrinterDeviceInfo> devices = <PrinterDeviceInfo>[];
    devices.clear();
    _subscription = printerManager.discovery(type: printType, isBle: isBle).listen((device) {
      devices.add(PrinterDeviceInfo(
        deviceName: device.name,
        address: device.address,
        isBle: isBle,
        vendorId: device.vendorId,
        productId: device.productId,
        typePrinter: printType,
      ));
    });
  }

  Future usbPrintTicket(SimpleAccount account) async {
    List<int> bytes = [];

    // Xprinter XP-N160I
    final profile = await CapabilityProfile.load(name: 'XP-N160I');

    // PaperSize.mm80 or PaperSize.mm58
    final generator = Generator(PaperSize.mm58, profile);
    bytes += generator.setGlobalCodeTable('CP1252');
    final ByteData data = await rootBundle.load('assets/login_logo_xian.png');
    if (data.lengthInBytes > 0) {
      final Uint8List imageBytes = data.buffer.asUint8List();
      // decode the bytes into an image
      final decodedImage = img.decodeImage(imageBytes)!;
      // Create a black bottom layer
      // Resize the image to a 130x? thumbnail (maintaining the aspect ratio).
      img.Image thumbnail = img.copyResize(decodedImage, height: 50);
      // creates a copy of the original image with set dimensions
      img.Image originalImg = img.copyResize(decodedImage, width: 580, height: 50);
      // fills the original image with a white background
      // img.fill(originalImg, color: img.ColorUint16.rgb(255, 255, 255));
      img.fill(originalImg, color: img.ColorRgb8(255, 255, 255));
      var padding = (originalImg.width - thumbnail.width) / 2;

      //insert the image inside the frame and center it
      drawImage(originalImg, thumbnail, dstX: padding.toInt());

      // convert image to grayscale
      var grayscaleImage = img.grayscale(originalImg);

      bytes += generator.feed(1);
      // bytes += generator.imageRaster(img.decodeImage(imageBytes)!, align: PosAlign.center);
      bytes += generator.imageRaster(grayscaleImage, align: PosAlign.center);
      bytes += generator.feed(1);
    }

    const PosStyles posStylesC = PosStyles(align: PosAlign.center, width: PosTextSize.size2, height: PosTextSize.size2);
    const PosStyles posStylesL = PosStyles(align: PosAlign.left, width: PosTextSize.size1, height: PosTextSize.size1);
    // bytes += generator.row([
    //   PosColumn(width: 12, text: account.mealType + '餐票', styles: posStylesC, containsChinese: true),
    // ]);
    // bytes += generator.emptyLines(1);
    // bytes += generator.text('    餐厅:'+account.position, styles: posStylesL, containsChinese: true);
    // bytes += generator.emptyLines(1);
    // bytes += generator.text('    学号:'+account.accountId, styles: posStylesL, containsChinese: true);
    // bytes += generator.emptyLines(1);
    // bytes += generator.text('    姓名:'+account.userName, styles: posStylesL, containsChinese: true);
    // bytes += generator.emptyLines(1);
    // bytes += generator.text('    费用:'+account.fee, styles: posStylesL, containsChinese: true);
    // bytes += generator.emptyLines(1);

    var now = new DateTime.now(); // 2019-06-20 16:59:05.560543
    String _nowTime = "${now.year.toString()}-${now.month.toString().padLeft(2,'0')}-${now.day.toString().padLeft(2,'0')} ${now.hour.toString().padLeft(2, '0')}:${now.minute.toString().padLeft(2, '0')}:${now.second.toString().padLeft(2, '0')}";
    bytes += generator.text('    时间:${_nowTime}', styles: posStylesL, containsChinese: true);
    bytes += generator.hr();

    PrinterDeviceInfo printerDeviceInfo = new PrinterDeviceInfo();
    printerDeviceInfo.deviceName = '资讯组打印机';
    printerDeviceInfo.typePrinter = PrinterType.usb;
    usbPrint(bytes, generator, printerDeviceInfo);
  }

  usbPrint(List<int> bytes, Generator generator, PrinterDeviceInfo? selectedPrinter) async {
    var connectedTCP = false;
    if (selectedPrinter == null) return;
    var bluetoothPrinter = selectedPrinter!;

    switch (bluetoothPrinter.typePrinter) {
      case PrinterType.usb:
        bytes += generator.feed(2);
        bytes += generator.cut();
        await printerManager.connect(
            type: bluetoothPrinter.typePrinter,
            model: UsbPrinterInput(name: bluetoothPrinter.deviceName, productId: bluetoothPrinter.productId, vendorId: bluetoothPrinter.vendorId));
        pendingTask = null;
        break;
      case PrinterType.bluetooth:
        bytes += generator.cut();
        await printerManager.connect(
            type: bluetoothPrinter.typePrinter,
            model: BluetoothPrinterInput(
                name: bluetoothPrinter.deviceName,
                address: bluetoothPrinter.address!,
                isBle: bluetoothPrinter.isBle ?? false,
                autoConnect: _reconnect));
        pendingTask = null;
        break;
      case PrinterType.network:
        bytes += generator.feed(2);
        bytes += generator.cut();
        connectedTCP = await printerManager.connect(type: bluetoothPrinter.typePrinter, model: TcpPrinterInput(ipAddress: bluetoothPrinter.address!));
        if (!connectedTCP) print(' --- 请检查您的连接 ---');
        break;
      default:
    }
    if (bluetoothPrinter.typePrinter == PrinterType.bluetooth && Platform.isAndroid) {
      if (_currentStatus == BTStatus.connected) {
        printerManager.send(type: bluetoothPrinter.typePrinter, bytes: bytes);
        pendingTask = null;
      }
    } else {
      printerManager.send(type: bluetoothPrinter.typePrinter, bytes: bytes);
    }
  }

  PrinterManager getPrinterManagerContext() {
    return printerManager;
  }

}
